package com.micro.ai.files.service.impl;

import com.micro.ai.commons.exception.BusinessException;
import com.micro.ai.files.config.MinioConfig;
import com.micro.ai.files.service.StorageService;
import io.minio.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;

/**
 * MinIO存储服务实现
 * 
 * @author micro-ai
 * @since 0.0.1
 */
@Slf4j
@Service
public class MinioStorageServiceImpl implements StorageService {

    @Autowired
    private MinioClient minioClient;

    @Autowired
    private MinioConfig minioConfig;

    /**
     * 确保存储桶存在
     */
    private void ensureBucketExists() {
        try {
            boolean found = minioClient.bucketExists(BucketExistsArgs.builder()
                    .bucket(minioConfig.getBucketName())
                    .build());
            if (!found) {
                minioClient.makeBucket(MakeBucketArgs.builder()
                        .bucket(minioConfig.getBucketName())
                        .build());
                log.info("创建MinIO存储桶: {}", minioConfig.getBucketName());
            }
        } catch (Exception e) {
            log.error("检查或创建MinIO存储桶失败", e);
            throw new BusinessException("F0004", "存储服务初始化失败: " + e.getMessage());
        }
    }

    @Override
    public String uploadFile(MultipartFile file, String objectName) {
        try {
            ensureBucketExists();
            
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(minioConfig.getBucketName())
                    .object(objectName)
                    .stream(file.getInputStream(), file.getSize(), -1)
                    .contentType(file.getContentType())
                    .build());
            
            log.info("文件上传成功: bucket={}, object={}, size={}", 
                    minioConfig.getBucketName(), objectName, file.getSize());
            
            return getFileUrl(objectName);
        } catch (Exception e) {
            log.error("文件上传失败: object={}", objectName, e);
            throw new BusinessException("F0003", "文件上传失败: " + e.getMessage());
        }
    }

    @Override
    public String uploadFile(InputStream inputStream, String objectName, String contentType, long size) {
        try {
            ensureBucketExists();
            
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(minioConfig.getBucketName())
                    .object(objectName)
                    .stream(inputStream, size, -1)
                    .contentType(contentType)
                    .build());
            
            log.info("文件流上传成功: bucket={}, object={}, size={}", 
                    minioConfig.getBucketName(), objectName, size);
            
            return getFileUrl(objectName);
        } catch (Exception e) {
            log.error("文件流上传失败: object={}", objectName, e);
            throw new BusinessException("F0003", "文件上传失败: " + e.getMessage());
        }
    }

    @Override
    public Resource downloadFile(String objectName) {
        try {
            InputStream inputStream = minioClient.getObject(GetObjectArgs.builder()
                    .bucket(minioConfig.getBucketName())
                    .object(objectName)
                    .build());
            
            return new InputStreamResource(inputStream);
        } catch (Exception e) {
            log.error("文件下载失败: object={}", objectName, e);
            throw new BusinessException("F0005", "文件下载失败: " + e.getMessage());
        }
    }

    @Override
    public InputStream getFileInputStream(String objectName) {
        try {
            return minioClient.getObject(GetObjectArgs.builder()
                    .bucket(minioConfig.getBucketName())
                    .object(objectName)
                    .build());
        } catch (Exception e) {
            log.error("获取文件流失败: object={}", objectName, e);
            throw new BusinessException("F0005", "获取文件流失败: " + e.getMessage());
        }
    }

    @Override
    public boolean deleteFile(String objectName) {
        try {
            minioClient.removeObject(RemoveObjectArgs.builder()
                    .bucket(minioConfig.getBucketName())
                    .object(objectName)
                    .build());
            
            log.info("文件删除成功: bucket={}, object={}", minioConfig.getBucketName(), objectName);
            return true;
        } catch (Exception e) {
            log.error("文件删除失败: object={}", objectName, e);
            return false;
        }
    }

    @Override
    public boolean fileExists(String objectName) {
        try {
            minioClient.statObject(StatObjectArgs.builder()
                    .bucket(minioConfig.getBucketName())
                    .object(objectName)
                    .build());
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    @Override
    public String getFileUrl(String objectName, int expirySeconds) {
        try {
            String url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                    .method(io.minio.http.Method.GET)
                    .bucket(minioConfig.getBucketName())
                    .object(objectName)
                    .expiry(expirySeconds)
                    .build());
            return url;
        } catch (Exception e) {
            log.error("生成文件访问URL失败: object={}", objectName, e);
            throw new BusinessException("F0006", "生成文件访问URL失败: " + e.getMessage());
        }
    }

    @Override
    public String getFileUrl(String objectName) {
        // 生成预签名URL（7天有效期）
        return getFileUrl(objectName, 7 * 24 * 3600); // 7天
    }
}

